// *********************************************************************************
// Project Name : zkx2024
// Author       : xfsong
// Email        : 1293993416@qq.com
// Create Time  : 2024-04-22
// File Name    : dsp.v
// Module Name  :
// Called By    :
// Abstract     :
//
// 
// *********************************************************************************
// Modification History:
// Date         By              Version                 Change Description
// -----------------------------------------------------------------------
// 2024-04-22    Macro           1.0                     Original
//  
// *********************************************************************************


// ---------------------------cac_dsp is used to dispatch data to four different cac units------------------------------------------
module dsp#(
    parameter FIX_ADDR = 0   //united map with 5bit  0xxxx, FIX_ADDR should be 4bit
)(
    input             CLK, RST_N,
    
    input   [0:0]     SRAM_VLD_I,
    input   [3:0]     SRAM_SHARE_I,

    input   [0:0]     SRAM_RELEASE_VLD_I,
    input   [3:0]     SRAM_RELEASE_I,    //input from top module

    input   [0:0]     RD_DATA_VLD,
    input   [29:0]    RD_DATA_VALUE,


    st_imc_bus.imc  i00_imc_ports,
    st_imc_bus.imc  i01_imc_ports,
    st_imc_bus.imc  i02_imc_ports,
    st_imc_bus.imc  i03_imc_ports,

    /**request for address is under to be designed**/
    //input   [3:0]     WR_REQ_I0, WR_REQ_I1, WR_REQ_I2, WR_REQ_I3,
    //input   


    dsp_cac_bus.dsp_ports i0_dsp_ports,
    dsp_cac_bus.dsp_ports i1_dsp_ports,
    dsp_cac_bus.dsp_ports i2_dsp_ports,
    dsp_cac_bus.dsp_ports i3_dsp_ports
);

//wire [2:0] ocup_status;
wire [5:0] cac0_sram;
reg  [5:0] cac1_sram, cac2_sram, cac3_sram; //bit-5 means whether this cac is used  bit0-4presents sram block number

//-------------------------one read bus from st drive four read bus of 4 cacs in one imc
reg  [0:0]  rd_data_vld_cac0,   rd_data_vld_cac1,   rd_data_vld_cac2,   rd_data_vld_cac3;
reg  [29:0] rd_data_value_cac0, rd_data_value_cac1, rd_data_value_cac2, rd_data_value_cac3;
//------------------------
//------------------------4 cacX_share signal to be passed to 4 cac
wire [0:0] cac1_share, cac2_share, cac3_share;
//------------------------

//reg  [29:0] data_value_cac0, data_value_cac1, data_value_cac2, data_value_cac3;
//reg  [1:0]  data_vld_cac0, data_vld_cac1, data_vld_cac2, data_vld_cac3; //one-hot  bit-1 represents whether is valid, bit-0 represents read or write:1-write, 0-read;
//-----------------signal access fed through dsp fromst to 4 cacs, just wire
/*
wire  [0:0]  wr_data_vld_cac0,   wr_data_vld_cac1,   wr_data_vld_cac2,   wr_data_vld_cac3; 
wire  [29:0] wr_data_value_cac0, wr_data_value_cac1, wr_data_value_cac2, wr_data_value_cac3;
wire  [0:0]  wr_req_cac0,   wr_req_cac1,    wr_req_cac2,    wr_req_cac3;
wire  [0:0]  wr_vld_cac0,   wr_vld_cac1,    wr_vld_cac2,    wr_vld_cac3;
wire  [17:0] wr_addr_cac0,  wr_addr_cac1,   wr_addr_cac2,   wr_addr_cac3;
*/
//-------------------------------------------------------

//-----------------------------7 assign here from st_imc_bus to dsp_cac_bus
assign i0_dsp_ports.WR_REQ_CAC = i00_imc_ports.WR_REQ;      //st->cac
assign i0_dsp_ports.WR_DATA_VLD_CAC = i00_imc_ports.WR_DATA_VLD;
assign i0_dsp_ports.WR_DATA_VALUE_CAC = i00_imc_ports.WR_DATA_VALUE;
assign i0_dsp_ports.RD_DATA_VLD_CAC = rd_data_vld_cac0;
assign i0_dsp_ports.RD_DATA_VALUE_CAC = rd_data_value_cac0;
assign i0_dsp_ports.CAC_SRAM = cac0_sram;                   //dsp->cac  note:fix_cac has nocac_share
assign i00_imc_ports.WR_VLD = i0_dsp_ports.WR_VLD_CAC;      //cac->st
assign i00_imc_ports.WR_ADDR = i0_dsp_ports.WR_ADDR_CAC;

assign i1_dsp_ports.WR_REQ_CAC = i01_imc_ports.WR_REQ;
assign i1_dsp_ports.WR_DATA_VLD_CAC = i01_imc_ports.WR_DATA_VLD;
assign i1_dsp_ports.WR_DATA_VALUE_CAC = i01_imc_ports.WR_DATA_VALUE;
assign i1_dsp_ports.RD_DATA_VLD_CAC = rd_data_vld_cac1;
assign i1_dsp_ports.RD_DATA_VALUE_CAC = rd_data_value_cac1;
assign i1_dsp_ports.CAC_SRAM = cac1_sram;
assign i1_dsp_ports.CAC_SHARE = cac1_share;
assign i01_imc_ports.WR_VLD = i1_dsp_ports.WR_VLD_CAC;
assign i01_imc_ports.WR_ADDR = i1_dsp_ports.WR_ADDR_CAC;

assign i2_dsp_ports.WR_REQ_CAC = i02_imc_ports.WR_REQ;
assign i2_dsp_ports.WR_DATA_VLD_CAC = i02_imc_ports.WR_DATA_VLD;
assign i2_dsp_ports.WR_DATA_VALUE_CAC = i02_imc_ports.WR_DATA_VALUE;
assign i2_dsp_ports.RD_DATA_VLD_CAC = rd_data_vld_cac2;
assign i2_dsp_ports.RD_DATA_VALUE_CAC = rd_data_value_cac2;
assign i2_dsp_ports.CAC_SRAM = cac2_sram;
assign i2_dsp_ports.CAC_SHARE = cac2_share;
assign i02_imc_ports.WR_VLD = i2_dsp_ports.WR_VLD_CAC;
assign i02_imc_ports.WR_ADDR = i2_dsp_ports.WR_ADDR_CAC;

assign i3_dsp_ports.WR_REQ_CAC = i03_imc_ports.WR_REQ;
assign i3_dsp_ports.WR_DATA_VLD_CAC = i03_imc_ports.WR_DATA_VLD;
assign i3_dsp_ports.WR_DATA_VALUE_CAC = i03_imc_ports.WR_DATA_VALUE;
assign i3_dsp_ports.RD_DATA_VLD_CAC = rd_data_vld_cac3;
assign i3_dsp_ports.RD_DATA_VALUE_CAC = rd_data_value_cac3;
assign i3_dsp_ports.CAC_SRAM = cac3_sram;  
assign i3_dsp_ports.CAC_SHARE = cac3_share;
assign i03_imc_ports.WR_VLD = i3_dsp_ports.WR_VLD_CAC;
assign i03_imc_ports.WR_ADDR = i3_dsp_ports.WR_ADDR_CAC;
//-------------------------------------------------------------------------
//cac for fix_sram
assign cac0_sram[5] = 1'b1;
assign cac0_sram[4:0] = {1'b0,FIX_ADDR};

//dispatch cac for share_sram

always@(posedge CLK or negedge RST_N)begin
    if(!RST_N)
        cac1_sram <= 6'd0;
    else if(SRAM_VLD_I)begin
        if(cac1_sram[5] == 1'b0)begin
            cac1_sram <= {1'b1,1'b1,SRAM_SHARE_I};
        end
    end
    else if(SRAM_RELEASE_VLD_I)begin
        if(SRAM_RELEASE_I == cac1_sram[3:0])
            cac1_sram <= {1'b0,1'b1,SRAM_RELEASE_I};
    end
end
assign cac1_share = SRAM_VLD_I && (!cac1_sram[5])? 1'b1:1'b0;



always@(posedge CLK or negedge RST_N)begin
    if(!RST_N)
        cac2_sram <= 6'd0;
    else if(SRAM_VLD_I)begin
        if((cac1_sram[5] == 1'b1) && (cac2_sram[5] == 1'b0))begin
            cac2_sram <= {1'b1,1'b1,SRAM_SHARE_I};
        end
    end
    else if(SRAM_RELEASE_VLD_I)begin
        if(SRAM_RELEASE_I== cac2_sram[3:0])
            cac2_sram <= {1'b0,1'b1,SRAM_RELEASE_I};
    end
end

assign cac2_share = SRAM_VLD_I && cac1_sram[5] && (!cac2_sram[5])? 1'b1:1'b0;

always@(posedge CLK or negedge RST_N)begin
    if(!RST_N)
        cac3_sram <= 6'd0;
    else if(SRAM_VLD_I)begin
        if((cac1_sram[5] == 1'b1) && (cac2_sram[5] == 1'b1) && (cac3_sram[5] == 1'b0))begin
            cac3_sram <= {1'b1,1'b1,SRAM_SHARE_I};
        end
    end
    else if(SRAM_RELEASE_VLD_I)begin
        if(SRAM_RELEASE_I== cac3_sram[3:0])
            cac3_sram <= {1'b0,1'b1,SRAM_RELEASE_I};
    end
end

assign cac3_share = SRAM_VLD_I && cac1_sram[5] && cac2_sram[5] && (!cac3_sram[5])? 1'b1:1'b0;
// ------------------------dipatch read-logic
always@(*)begin
    rd_data_vld_cac0 = 1'b0; 
    rd_data_value_cac0 = 30'd0;
    rd_data_vld_cac1 = 1'b0; 
    rd_data_value_cac1 = 30'd0;
    rd_data_vld_cac2 = 1'b0; 
    rd_data_value_cac2 = 30'd0;
    rd_data_vld_cac3 = 1'b0; 
    rd_data_value_cac3 = 30'd0;
    if(RD_DATA_VLD)begin
        case(RD_DATA_VALUE[27:23])
            cac0_sram[4:0]: begin 
                                rd_data_vld_cac0 = 1'b1;
                                rd_data_value_cac0 = RD_DATA_VALUE;
                            end
            cac1_sram[4:0]:begin
                                rd_data_vld_cac1 = 1'b1;
                                rd_data_value_cac1 = RD_DATA_VALUE;
                            end
            cac2_sram[4:0]:begin
                                rd_data_vld_cac2 = 1'b1;
                                rd_data_value_cac2 = RD_DATA_VALUE;
                            end
            cac3_sram[4:0]:begin
                                rd_data_vld_cac3 = 1'b1;
                                rd_data_value_cac3 = RD_DATA_VALUE;
                            end
        endcase
    end
    /*
    else begin
        rd_data_vld_cac0 = 1'b0; 
        rd_data_value_cac0 = 30'd0;
        rd_data_vld_cac1 = 1'b0; 
        rd_data_value_cac1 = 30'd0;
        rd_data_vld_cac2 = 1'b0; 
        rd_data_value_cac2 = 30'd0;
        rd_data_vld_cac3 = 1'b0; 
        rd_data_value_cac3 = 30'd0;
    end
    */
end

endmodule
/*
//dispatch value
always@(*)begin
    data_value_cac0 = 30'd0;
    data_value_cac1 = 30'd0;
    data_value_cac2 = 30'd0;
    data_value_cac3 = 30'd0;
    data_vld_cac0 = 1'd0;
    data_vld_cac1 = 1'd0;
    data_vld_cac2 = 1'd0;
    data_vld_cac3 = 1'd0;
    if(RD_DATA_VLD || WR_DATA_VLD_I0 || WR_DATA_VLD_I1 || WR_DATA_VLD_I2 || WR_DATA_VLD_I3)begin
        if(RD_DATA_VLD)begin
            case(WR_DATA_VALUE_I0[27:23])
                cac0_sram[4:0]:begin
                                data_value_cac0 = RD_DATA_VALUE;
                                data_vld_cac0 = 2'b10;
                                end
                cac1_sram[4:0]:begin
                                data_value_cac1 = RD_DATA_VALUE;
                                data_vld_cac1 = 2'b10;
                                end
                cac2_sram[4:0]:begin
                                data_value_cac2 = RD_DATA_VALUE;
                                data_vld_cac2 = 2'b10;
                                end
                cac3_sram[4:0]:begin
                                data_value_cac3 = RD_DATA_VALUE;
                                data_vld_cac3 = 2'b10;
                                end
            endcase
        end
        if(WR_DATA_VLD_I0)begin
            case(WR_DATA_VALUE_I0[27:23])
                cac0_sram[4:0]:begin
                                data_value_cac0 = WR_DATA_VALUE_I0;
                                data_vld_cac0 = 2'b11;
                                end
                cac1_sram[4:0]:begin
                                data_value_cac1 = WR_DATA_VALUE_I0;
                                data_vld_cac1 = 2'b11;
                                end
                cac2_sram[4:0]:begin
                                data_value_cac2 = WR_DATA_VALUE_I0;
                                data_vld_cac2 = 2'b11;
                                end
                cac3_sram[4:0]:begin
                                data_value_cac3 = WR_DATA_VALUE_I0;
                                data_vld_cac3 = 2'b11;
                                end
            endcase
        end
        if(WR_DATA_VLD_I1)begin
            case(WR_DATA_VALUE_I1[27:23])
                cac0_sram[4:0]:begin
                                data_value_cac0 = WR_DATA_VALUE_I1;
                                data_vld_cac0 = 2'b11;
                                end
                cac1_sram[4:0]:begin
                                data_value_cac1 = WR_DATA_VALUE_I1;
                                data_vld_cac1 = 2'b11;
                                end
                cac2_sram[4:0]:begin
                                data_value_cac2 = WR_DATA_VALUE_I1;
                                data_vld_cac2 = 2'b11;
                                end
                cac3_sram[4:0]:begin
                                data_value_cac3 = WR_DATA_VALUE_I1;
                                data_vld_cac3 = 2'b11;
                                end
            endcase
        end
        if(WR_DATA_VLD_I2)begin
            case(WR_DATA_VALUE_I2[27:23])
                cac0_sram[4:0]:begin
                                data_value_cac0 = WR_DATA_VALUE_I2;
                                data_vld_cac0 = 2'b11;
                                end
                cac1_sram[4:0]:begin
                                data_value_cac1 = WR_DATA_VALUE_I2;
                                data_vld_cac1 = 2'b11;
                                end
                cac2_sram[4:0]:begin
                                data_value_cac2 = WR_DATA_VALUE_I2;
                                data_vld_cac2 = 2'b11;
                                end
                cac3_sram[4:0]:begin
                                data_value_cac3 = WR_DATA_VALUE_I2;
                                data_vld_cac3 = 2'b11;
                                end
            endcase
        end
        if(WR_DATA_VLD_I3)begin
            case(WR_DATA_VALUE_I3[27:23])
                cac0_sram[4:0]:begin
                                data_value_cac0 = WR_DATA_VALUE_I3;
                                data_vld_cac0 = 2'b11;
                                end
                cac1_sram[4:0]:begin
                                data_value_cac1 = WR_DATA_VALUE_I3;
                                data_vld_cac1 = 2'b11;
                                end
                cac2_sram[4:0]:begin
                                data_value_cac2 = WR_DATA_VALUE_I3;
                                data_vld_cac2 = 2'b11;
                                end
                cac3_sram[4:0]:begin
                                data_value_cac3 = WR_DATA_VALUE_I3;
                                data_vld_cac3 = 2'b11;
                                end
            endcase
        end
    end
end
*/
                
        
/*
always@(*)begin
    data_value_cac0 = 'd0;
    data_value_cac1 = 'd0;
    data_value_cac2 = 'd0;
    data_value_cac3 = 'd0;
    data_vld_cac0 = 'd0;
    data_vld_cac1 = 'd0;
    data_vld_cac2 = 'd0;
    data_vld_cac3 = 'd0;
    if(DATA_VLD_I)begin
        case(DATA_VALUE_I[27:23])
            cac0_sram[4:0]:begin
                            data_value_cac0 = DATA_VALUE_I;
                            data_vld_cac0 = 1'b1;
                            end
            cac1_sram[4:0]:begin
                            data_value_cac1 = DATA_VALUE_I;
                            data_vld_cac1 = 1'b1;
                            end
            cac2_sram[4:0]:begin
                            data_value_cac2 = DATA_VALUE_I;
                            data_vld_cac2 = 1'b1;
                            end
            cac3_sram[4:0]:begin
                            data_value_cac3 = DATA_VALUE_I;
                            data_vld_cac3 = 1'b1;
                            end
        endcase
    end
end
*/
    
//address require from up module(top)   
/*
always@(*)begin
    wr_req_vld0 = 1'b000;
    if(WR_REQ_I0 == cac0_sram[4:0])  
        wr_req_vld0 = 1'b100;
    else if(WR_REQ_I1 == cac0_sram[4:0])
        wr_req_vld0 = 1'b101;
    else if(WR_REQ_I2 == cac0_sram[4:0])
        wr_req_vld0 = 1'b110;
    else if(WR_REQ_I3 == cac0_sram[4:0])
        wr_req_vld0 = 1'b111;
end

always@(*)begin
    wr_req_vld1 = 1'b000;
    if(WR_REQ_I0 == cac1_sram[4:0])  
        wr_req_vld1 = 1'b100;
    else if(WR_REQ_I1 == cac1_sram[4:0])
        wr_req_vld1 = 1'b101;
    else if(WR_REQ_I2 == cac1_sram[4:0])
        wr_req_vld1 = 1'b110;
    else if(WR_REQ_I3 == cac1_sram[4:0])
        wr_req_vld1 = 1'b111;
end

always@(*)begin
    wr_req_vld2 = 1'b000;
    if(WR_REQ_I0 == cac2_sram[4:0])  
        wr_req_vld2 = 1'b100;
    else if(WR_REQ_I1 == cac2_sram[4:0])
        wr_req_vld2 = 1'b101;
    else if(WR_REQ_I2 == cac2_sram[4:0])
        wr_req_vld2 = 1'b110;
    else if(WR_REQ_I3 == cac2_sram[4:0])
        wr_req_vld2 = 1'b111;
end

always@(*)begin
    wr_req_vld3 = 1'b000;
    if(WR_REQ_I0 == cac3_sram[4:0])  
        wr_req_vld3 = 1'b100;
    else if(WR_REQ_I1 == cac3_sram[4:0])
        wr_req_vld3 = 1'b101;
    else if(WR_REQ_I2 == cac3_sram[4:0])
        wr_req_vld3 = 1'b110;
    else if(WR_REQ_I3 == cac3_sram[4:0])
        wr_req_vld3 = 1'b111;
end
*/
